const express = require('express')
const cors = require('cors')
const next = require('next')
const { createProxyMiddleware } = require('http-proxy-middleware')
const configs = require('./src/configs/server')
// const fileProxy = require('./middlewares/fileProxy')
const fs = require('fs')
const https = require('https')

const port = 8080
const sslPort = 443
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

function apiProxy(apiList) {
  const targetIndex = process.env.NEXT_PUBLIC_ENV === 'production' ? 1 : 0
  const scopeMap = new Map()
  const apiRows = apiList.reduce((prev, scope) => {
    return [
      {
        path: `${scope.scope}/`,
        mockTarget: scope.mockTarget,
        scope: scope.scope,
        target: scope.target,
      },
      ...prev,
    ]
  }, [])

  apiRows.forEach((apiRow) => {
    scopeMap.set(
      apiRow.path,
      createProxyMiddleware({
        logLevel:
          process.env.NEXT_PUBLIC_ENV !== 'production' ? 'debug' : 'silent',
        changeOrigin: true,
        target:
          process.env.NEXT_PUBLIC_ENV === 'development'
            ? apiRow.mockTarget || apiRow.target[targetIndex]
            : apiRow.target[targetIndex],
        pathRewrite: {
          [`${process.env.NEXT_PUBLIC_BASE_PATH}${apiRow.scope}`]: '',
        },
        onError(err) {
          console.error('[apiProxy] error: ', err)
        },
        onProxyReq: function (proxyReq) {
          // 禁用缓存
          proxyReq.setHeader('Cache-Control', 'no-store')
        },
      })
    )
  })

  const apiRowWithPath = (path) => {
    return apiRows.find((api) => {
      return path.startsWith(api.path)
    })
  }

  const proxy = (req, res, next) => {
    const apiRow = apiRowWithPath(req.path)

    if (apiRow) {
      const proxyMw = scopeMap.get(apiRow.path)
      proxyMw(req, res, next)
    } else {
      res
        .status(400)
        .send(`[apiProxy] Proxy Service did not set ${req.method}:${req.path}`)
    }
  }

  return proxy
}

app.prepare().then(() => {
  const server = express()

  server.use(cors())

  server.get('/health', (req, res) => {
    res.send('Health')
  })

  // 将接口代理到 /papi
  server.use('/papi', apiProxy(configs.apiList))

  // server.use('/fileproxy', fileProxy)

  server.all('*', (req, res) => {
    return handle(req, res)
  })

  if (!process.env.SERVER_PROTOCOL) {
    server.listen(port, (err) => {
      if (err) throw err
      console.log(`>${configs.appName} Ready on http://localhost:${port}`)
    })
  } else {
    const key = fs.readFileSync('staging.aichatting.net-key.pem', 'utf-8')
    const cert = fs.readFileSync('staging.aichatting.net.pem', 'utf-8')
    https.createServer({ key, cert }, server).listen(sslPort, (err) => {
      if (err) throw err
      console.log(
        `>${configs.appName} Ready on ${process.env.NEXT_PUBLIC_HOST}`
      )
    })
  }
})
